package com.ikingtech.framework.sdk.authenticate.embedded.authenticate;

import com.ikingtech.framework.sdk.authenticate.embedded.core.Credential;
import com.ikingtech.framework.sdk.cache.constants.CacheConstants;
import com.ikingtech.framework.sdk.context.security.Identity;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.utils.Tools;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.List;

import static com.ikingtech.framework.sdk.context.constant.SecurityConstants.TOKEN_PREFIX;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
public class DelegateAuthenticate {

    private final List<Authenticate> authenticates;

    private final StringRedisTemplate redisTemplate;

    public Identity authenticate(Credential credential) {
        for (Authenticate authenticate : authenticates) {
            if (Boolean.TRUE.equals(authenticate.support(credential))) {
                return authenticate.verify(credential);
            }
        }
        throw new FrameworkException("invalidCredential");
    }

    public void cancelAuthenticate(String authorization) {
        String accessTokenKey = CacheConstants.accessTokenKeyFormatWithoutPrefix(authorization);
        Identity identity = Tools.Json.toBean(this.redisTemplate.opsForValue().get(accessTokenKey), Identity.class);
        if (identity != null) {
            String currentTokenWithoutPrefix = authorization.replace(TOKEN_PREFIX, "");
            this.redisTemplate.delete(accessTokenKey);
            this.redisTemplate.opsForList().remove(CacheConstants.loginUserFormat(identity.getId(), identity.getEndpoint()), 0, currentTokenWithoutPrefix);
            Long tokenCount = this.redisTemplate.opsForList().size(CacheConstants.loginUserFormat(identity.getId(), identity.getEndpoint()));
            if (tokenCount == null || 1L > tokenCount) {
                this.redisTemplate.delete(CacheConstants.loginUserFormat(identity.getId(), identity.getEndpoint()));
                this.redisTemplate.delete(CacheConstants.userAuthDetailsFormat(identity.getUsername(), Me.tenantCode()));
            }
        }
    }
}
